package com.jvm.condition;

import java.util.concurrent.TimeUnit;

// synchronized 中等待和唤醒线程示例
public class Demo1 {

    static Object lock = new Object();

    public static class T1 extends Thread {

        @Override
        public void run() {
             System.out.println(System.currentTimeMillis() + "," +
                        this.getName() + " 准备获取锁！");
            synchronized (lock) {
                System.out.println(System.currentTimeMillis() + "," +
                        this.getName() + " 获取锁成功！");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(System.currentTimeMillis() + "," +
                        this.getName() + " 释放锁成功！");
        }
    }

    public static class T2 extends Thread {

        @Override
        public void run() {
             System.out.println(System.currentTimeMillis() + "," +
                        this.getName() + " 准备获取锁！");
            synchronized (lock) {
                System.out.println(System.currentTimeMillis() + "," +
                        this.getName() + " 获取锁成功！");
                lock.notify();
                System.out.println(System.currentTimeMillis() + "," +
                        this.getName() + " notify！");
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(System.currentTimeMillis() + "," +
                        this.getName() + " 准备释放锁！");
            }
            System.out.println(System.currentTimeMillis() + "," +
                        this.getName() + " 释放锁成功！");
        }
    }

    public static void main(String[] args) throws InterruptedException {

        T1 t1 = new T1();
        t1.setName("t1");
        t1.start();
        TimeUnit.SECONDS.sleep(5);

        T2 t2 = new T2();
        t2.setName("t2");
        t2.start();


        /**
         *
1、 线程 t1 先获取锁，然后调用了 wait()方法将线程置为等待状态，然后会释放 lock 的锁
2、 主线程等待 5 秒之后，启动线程 t2，t2 获取到了锁，结果中 1、3 行时间相差 5 秒左右
3、 t2 调用 lock.notify()方法，准备将等待在 lock 上的线程 t1 唤醒，notify()方法之后又休眠了 5 秒，
         看一下输出的 5、8 可知，notify()方法之后，t1 并不能立即被唤醒，需要等到 t2 将 synchronized 块执行完毕，释放锁之后，t1 才被唤醒
4、 wait()方法和 notify()方法必须放在同步块内调用（synchronized 块内），否则会报错
         *
         */
    }

}
